Scikit-learn์ ์ฐจ์ ์ถ์ ํน์ง ์ ํ ๊ธฐ๋ฒ์ ๋ํ ์ข ํฉ ๊ฐ์ด๋๋ก, ์ ์ธ๊ณ ๋ฐ์ดํฐ ๊ณผํ ์ค๋ฌด์๋ค์ด ํจ์จ์ ์ด๊ณ ๊ฒฌ๊ณ ํ ๋ชจ๋ธ์ ๊ตฌ์ถํ ์ ์๋๋ก ์ง์ํฉ๋๋ค.
Scikit-learn ํน์ง ์ ํ: ๊ธ๋ก๋ฒ ๋ฐ์ดํฐ์ ์ ์ํ ์ฐจ์ ์ถ์ ๋ง์คํฐํ๊ธฐ
๋์์์ด ํ์ฅ๋๋ ๋ฐ์ดํฐ์ ์ธ๊ณ์์ ๋ฐฉ๋ํ ํน์ง์ ์์ ์๋ฌด๋ฆฌ ์ ๊ตํ ๋จธ์ ๋ฌ๋ ๋ชจ๋ธ์ด๋ผ ํ ์ง๋ผ๋ ์๋ํ ์ ์์ต๋๋ค. ํํ "์ฐจ์์ ์ ์ฃผ"๋ผ๊ณ ๋ถ๋ฆฌ๋ ์ด ํ์์ ๊ณ์ฐ ๋น์ฉ ์ฆ๊ฐ, ๋ชจ๋ธ ์ ํ๋ ๊ฐ์, ๊ทธ๋ฆฌ๊ณ ํด์ ๊ฐ๋ฅ์ฑ ์ ํ๋ก ์ด์ด์ง ์ ์์ต๋๋ค. ๋คํํ ํน์ง ์ ํ(feature selection) ๋ฐ ์ฐจ์ ์ถ์(dimensionality reduction) ๊ธฐ๋ฒ์ ๊ฐ๋ ฅํ ํด๊ฒฐ์ฑ ์ ์ ์ํฉ๋๋ค. Python ๋จธ์ ๋ฌ๋ ์ํ๊ณ์ ์ด์์ธ Scikit-learn์ ์ด๋ฌํ ๊ณผ์ ๋ฅผ ํจ๊ณผ์ ์ผ๋ก ํด๊ฒฐํ ์ ์๋ ํ๋ถํ ๋๊ตฌ ๋ชจ์์ ์ ๊ณตํ์ฌ ์ ์ธ๊ณ ๋ฐ์ดํฐ ๊ณผํ์๋ค์๊ฒ ์์ด์๋ ์ ๋ ์์์ด ๋๊ณ ์์ต๋๋ค.
์ด ์ข ํฉ ๊ฐ์ด๋๋ ์ฐจ์ ์ถ์์ ์ค์ ์ ๋๊ณ Scikit-learn์ ํน์ง ์ ํ ๊ธฐ๋ฅ์ ๋ณต์ก์ฑ์ ๊น์ด ์๊ฒ ๋ค๋ฃฐ ๊ฒ์ ๋๋ค. ๋ค์ํ ๋ฐฉ๋ฒ๋ก , ๊ทธ ๊ธฐ๋ณธ ์๋ฆฌ, ์ฝ๋ ์์ ๋ฅผ ํตํ ์ค์ ๊ตฌํ, ๊ทธ๋ฆฌ๊ณ ๋ค์ํ ๊ธ๋ก๋ฒ ๋ฐ์ดํฐ์ ์ ๋ํ ๊ณ ๋ ค ์ฌํญ์ ํ๊ตฌํ ๊ฒ์ ๋๋ค. ์ฐ๋ฆฌ์ ๋ชฉํ๋ ์ฑ์ฅํ๋ ๋ฐ์ดํฐ ์ ๋ฌธ๊ฐ์ ๋ ธ๋ จํ ๋ฐ์ดํฐ ์ค๋ฌด์ ์ฌ๋ฌ๋ถ์๊ฒ ํน์ง ์ ํ์ ๋ํ ์ ๋ณด์ ์ ๊ฐํ ๊ฒฐ์ ์ ๋ด๋ฆด ์ ์๋ ์ง์์ ์ ๊ณตํ์ฌ ๋ ํจ์จ์ ์ด๊ณ ์ ํํ๋ฉฐ ํด์ ๊ฐ๋ฅํ ๋จธ์ ๋ฌ๋ ๋ชจ๋ธ์ ๋ง๋ค ์ ์๋๋ก ํ๋ ๊ฒ์ ๋๋ค.
์ฐจ์ ์ถ์ ์ดํดํ๊ธฐ
Scikit-learn์ ํน์ ๋๊ตฌ๋ค์ ์์ธํ ์ดํด๋ณด๊ธฐ ์ ์, ์ฐจ์ ์ถ์์ ๊ธฐ๋ณธ ๊ฐ๋ ์ ํ์ ํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. ์ด ๊ณผ์ ์ ์ค์ํ ์ ๋ณด๋ฅผ ์ต๋ํ ๋ณด์กดํ๋ฉด์ ๋ฐ์ดํฐ๋ฅผ ๊ณ ์ฐจ์ ๊ณต๊ฐ์์ ์ ์ฐจ์ ๊ณต๊ฐ์ผ๋ก ๋ณํํ๋ ๊ฒ์ ํฌํจํฉ๋๋ค. ๊ทธ ์ด์ ์ ๋ค์ํฉ๋๋ค:
- ๊ณผ์ ํฉ ๊ฐ์: ํน์ง์ด ์ ์์๋ก ๋ชจ๋ธ์ด ๋จ์ํด์ง๊ณ , ํ๋ จ ๋ฐ์ดํฐ์ ๋ ธ์ด์ฆ๋ฅผ ํ์ตํ ๊ฐ๋ฅ์ฑ์ด ์ค์ด๋ญ๋๋ค.
- ํ๋ จ ์๊ฐ ๋จ์ถ: ํน์ง์ด ์ ์ ๋ชจ๋ธ์ ํจ์ฌ ๋ ๋น ๋ฅด๊ฒ ํ๋ จ๋ฉ๋๋ค.
- ๋ชจ๋ธ ํด์ ๊ฐ๋ฅ์ฑ ํฅ์: ์ ์ ์์ ํน์ง ๊ฐ์ ๊ด๊ณ๋ฅผ ์ดํดํ๊ธฐ ๋ ์ฝ์ต๋๋ค.
- ์ ์ฅ ๊ณต๊ฐ ๊ฐ์: ๋ฎ์ ์ฐจ์์ ๋ ์ ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ์๋ก ํฉ๋๋ค.
- ๋ ธ์ด์ฆ ๊ฐ์: ๊ด๋ จ ์๊ฑฐ๋ ์ค๋ณต๋๋ ํน์ง์ ์ ๊ฑฐํ์ฌ ๋ฐ์ดํฐ๋ฅผ ๋ ๊นจ๋ํ๊ฒ ๋ง๋ค ์ ์์ต๋๋ค.
์ฐจ์ ์ถ์๋ ํฌ๊ฒ ๋ ๊ฐ์ง ์ฃผ์ ์ ๊ทผ ๋ฐฉ์์ผ๋ก ๋ถ๋ฅํ ์ ์์ต๋๋ค:
1. ํน์ง ์ ํ
์ด ์ ๊ทผ ๋ฐฉ์์ ๋น๋ฉดํ ๋ฌธ์ ์ ๊ฐ์ฅ ๊ด๋ จ์ฑ์ด ๋์ ์๋ณธ ํน์ง์ ํ์ ์งํฉ์ ์ ํํ๋ ๊ฒ์ ํฌํจํฉ๋๋ค. ์๋ณธ ํน์ง์ ์ ์ง๋์ง๋ง ๊ทธ ์๊ฐ ์ค์ด๋ญ๋๋ค. ์ด๋ฅผ ๋ ์ํผ์ ๊ฐ์ฅ ์ํฅ๋ ฅ ์๋ ์ฌ๋ฃ๋ฅผ ์๋ณํ๊ณ ๋๋จธ์ง๋ ๋ฒ๋ฆฌ๋ ๊ฒ์ผ๋ก ์๊ฐํ ์ ์์ต๋๋ค.
2. ํน์ง ์ถ์ถ
์ด ์ ๊ทผ ๋ฐฉ์์ ์๋ณธ ํน์ง์ ์๋กญ๊ณ ๋ ์์ ํน์ง ์งํฉ์ผ๋ก ๋ณํํฉ๋๋ค. ์ด ์๋ก์ด ํน์ง๋ค์ ์๋ณธ ํน์ง์ ์กฐํฉ ๋๋ ํฌ์์ผ๋ก, ๋ฐ์ดํฐ์์ ๊ฐ์ฅ ์ค์ํ ๋ถ์ฐ์ด๋ ์ ๋ณด๋ฅผ ํฌ์ฐฉํ๋ ๊ฒ์ ๋ชฉํ๋ก ํฉ๋๋ค. ์ด๊ฒ์ ์๋ณธ ์ฌ๋ฃ์ ์ ์๋ฅผ ์ถ์ถํ๋ ๊ฒ๊ณผ ์ ์ฌํฉ๋๋ค.
Scikit-learn์ ์ด ๋ ๊ฐ์ง ์ ๊ทผ ๋ฐฉ์ ๋ชจ๋์ ๊ฐ๋ ฅํ ๋๊ตฌ๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ฐ๋ฆฌ๋ ์ข ์ข ํน์ง ์ ํ ๋๋ ์ถ์ถ์ ํตํด ์ฐจ์ ์ถ์์ ๊ธฐ์ฌํ๋ ๊ธฐ์ ์ ์ด์ ์ ๋ง์ถ ๊ฒ์ ๋๋ค.
Scikit-learn์ ํน์ง ์ ํ ๋ฐฉ๋ฒ
Scikit-learn์ ํน์ง ์ ํ์ ์ํํ๋ ์ฌ๋ฌ ๊ฐ์ง ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค. ์ด๋ค์ ํฌ๊ฒ ์ธ ๊ฐ์ง ๋ฒ์ฃผ๋ก ๋๋ ์ ์์ต๋๋ค:
1. ํํฐ ๋ฐฉ๋ฒ
ํํฐ ๋ฐฉ๋ฒ์ ํน์ ๋จธ์ ๋ฌ๋ ๋ชจ๋ธ๊ณผ ๋ ๋ฆฝ์ ์ผ๋ก ํน์ง์ ๊ณ ์ ํ ์์ฑ์ ๊ธฐ๋ฐ์ผ๋ก ํน์ง์ ๊ด๋ จ์ฑ์ ํ๊ฐํฉ๋๋ค. ์ด๋ค์ ์ผ๋ฐ์ ์ผ๋ก ๋น ๋ฅด๊ณ ๊ณ์ฐ ๋น์ฉ์ด ์ ๊ฒ ๋ค์ด ์ด๊ธฐ ๋ฐ์ดํฐ ํ์์ด๋ ๋งค์ฐ ํฐ ๋ฐ์ดํฐ์ ์ ๋ค๋ฃฐ ๋ ์ด์์ ์ ๋๋ค. ์ผ๋ฐ์ ์ธ ์งํ๋ก๋ ์๊ด๊ด๊ณ, ์ํธ ์ ๋ณด(mutual information) ๋ฐ ํต๊ณ์ ํ ์คํธ๊ฐ ์์ต๋๋ค.
a) ์๊ด๊ด๊ณ ๊ธฐ๋ฐ ํน์ง ์ ํ
ํ๊ฒ ๋ณ์์ ๋์ ์๊ด๊ด๊ณ๋ฅผ ๊ฐ์ง๋ ํน์ง์ ์ค์ํ๋ค๊ณ ๊ฐ์ฃผ๋ฉ๋๋ค. ๋ฐ๋๋ก, ์๋ก ๋์ ์๊ด๊ด๊ณ๋ฅผ ๊ฐ์ง๋ ํน์ง๋ค(๋ค์ค๊ณต์ ์ฑ)์ ์ค๋ณต๋ ์ ์์ผ๋ฉฐ ์ ๊ฑฐ๋ฅผ ๊ณ ๋ คํ ์ ์์ต๋๋ค. Scikit-learn์ feature_selection ๋ชจ๋์ ์ด๋ฅผ ๋๋ ๋๊ตฌ๋ค์ ์ ๊ณตํฉ๋๋ค.
์์: ๋ถ์ฐ ์๊ณ๊ฐ
๋ถ์ฐ์ด ๋งค์ฐ ๋ฎ์ ํน์ง์ ํ๋ณ๋ ฅ์ด ๊ฑฐ์ ์์ ์ ์์ต๋๋ค. VarianceThreshold ํด๋์ค๋ ํน์ ์๊ณ๊ฐ์ ์ถฉ์กฑํ์ง ์๋ ๋ถ์ฐ์ ๊ฐ์ง ํน์ง์ ์ ๊ฑฐํฉ๋๋ค. ์ด๋ ์ซ์ํ ํน์ง์ ํนํ ์ ์ฉํฉ๋๋ค.
from sklearn.feature_selection import VarianceThreshold
import numpy as np
X = [[0, 2, 0, 3], [0, 1, 4, 3], [0, 1, 1, 3]]
selector = VarianceThreshold(threshold=0.0)
selector.fit_transform(X)
# Output: array([[2, 0, 3], [1, 4, 3], [1, 1, 3]])
์ด ์์์์ ์ฒซ ๋ฒ์งธ ํน์ง(๋ชจ๋ 0)์ ๋ถ์ฐ์ด 0์ด๋ฏ๋ก ์ ๊ฑฐ๋ฉ๋๋ค. ์ด๋ ์์ธก ๋ฅ๋ ฅ์ด ์๋ ์์ ๋๋ ๊ฑฐ์ ์์์ธ ํน์ง์ ์ ๊ฑฐํ๋ ๊ธฐ๋ณธ์ ์ธ ๋์์ ํจ๊ณผ์ ์ธ ๋ฐฉ๋ฒ์ ๋๋ค.
์์: ํ๊ฒ๊ณผ์ ์๊ด๊ด๊ณ (Pandas ๋ฐ SciPy ์ฌ์ฉ)
Scikit-learn์๋ ๋ชจ๋ ํน์ง ์ ํ์ ๊ฑธ์ณ ํ๊ฒ๊ณผ์ ์๊ด๊ด๊ณ๋ฅผ ์ง์ ์ ์ผ๋ก ์ฒ๋ฆฌํ๋ ๊ณ ์์ค ํจ์๊ฐ ์์ง๋ง, ์ด๋ ์ผ๋ฐ์ ์ธ ์ ์ฒ๋ฆฌ ๋จ๊ณ์ ๋๋ค. ์ด๋ฅผ ์ํด Pandas์ SciPy๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
import pandas as pd
import numpy as np
from scipy.stats import pearsonr
# Sample data
data = {
'feature1': np.random.rand(100),
'feature2': np.random.rand(100) * 2,
'feature3': np.random.rand(100) - 1,
'target': np.random.randint(0, 2, 100)
}
df = pd.DataFrame(data)
# Calculate Pearson correlation with the target
correlations = df.corr()['target'].drop('target')
# Select features with correlation above a certain threshold (e.g., 0.2)
selected_features = correlations[abs(correlations) > 0.2].index.tolist()
print(f"Features correlated with target: {selected_features}")
์ด ์ฝ๋๋ ํ๊ฒ ๋ณ์์ ์ ํ ๊ด๊ณ๋ฅผ ๊ฐ์ง๋ ํน์ง์ ์๋ณํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ค๋๋ค. ์ด์ง ํ๊ฒ์ ๊ฒฝ์ฐ ์ ์ด์ฐ ์๊ด๊ด๊ณ(point-biserial correlation)๊ฐ ๊ด๋ จ์ฑ์ด ์์ผ๋ฉฐ, ๋ฒ์ฃผํ ํ๊ฒ์ ๊ฒฝ์ฐ ๋ค๋ฅธ ํต๊ณ ํ ์คํธ๊ฐ ๋ ์ ์ ํฉ๋๋ค.
b) ํต๊ณ์ ํ ์คํธ
ํํฐ ๋ฐฉ๋ฒ์ ํน์ง๊ณผ ํ๊ฒ ๋ณ์ ๊ฐ์ ์ข ์์ฑ์ ์ธก์ ํ๊ธฐ ์ํด ํต๊ณ์ ํ ์คํธ๋ฅผ ์ฌ์ฉํ ์๋ ์์ต๋๋ค. ์ด๋ ๋ฒ์ฃผํ ํน์ง์ ๋ค๋ฃจ๊ฑฐ๋ ๋ฐ์ดํฐ ๋ถํฌ์ ๋ํ ํน์ ๊ฐ์ ์ ํ ์ ์์ ๋ ํนํ ์ ์ฉํฉ๋๋ค.
Scikit-learn์ feature_selection ๋ชจ๋์ ๋ค์์ ์ ๊ณตํฉ๋๋ค:
f_classif: ๋ถ๋ฅ ์์ ์ ์ํ ๋ ์ด๋ธ/ํน์ง ๊ฐ์ ANOVA F-๊ฐ. ํน์ง์ ์ซ์ํ์ด๊ณ ํ๊ฒ์ ๋ฒ์ฃผํ์ด๋ผ๊ณ ๊ฐ์ ํฉ๋๋ค.f_regression: ํ๊ท ์์ ์ ์ํ ๋ ์ด๋ธ/ํน์ง ๊ฐ์ F-๊ฐ. ํน์ง์ ์ซ์ํ์ด๊ณ ํ๊ฒ์ ์ซ์ํ์ด๋ผ๊ณ ๊ฐ์ ํฉ๋๋ค.mutual_info_classif: ์ด์ฐํ ํ๊ฒ ๋ณ์์ ๋ํ ์ํธ ์ ๋ณด. ๋น์ ํ ๊ด๊ณ๋ฅผ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.mutual_info_regression: ์ฐ์ํ ํ๊ฒ ๋ณ์์ ๋ํ ์ํธ ์ ๋ณด.chi2: ๋ถ๋ฅ ์์ ์ ์ํ ์์๊ฐ ์๋ ํน์ง์ ์นด์ด์ ๊ณฑ ํต๊ณ. ๋ฒ์ฃผํ ํน์ง์ ์ฌ์ฉ๋ฉ๋๋ค.
์์: `f_classif` ๋ฐ `SelectKBest` ์ฌ์ฉ
SelectKBest๋ ์ ํํ ์ค์ฝ์ด๋ง ํจ์(์: f_classif)๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํน์ง์ ์ ํํ ์ ์๋๋ก ํ๋ ๋ฉํ ๋ณํ๊ธฐ์
๋๋ค.
from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectKBest, f_classif
iris = load_iris()
X, y = iris.data, iris.target
# Select the top 2 features using f_classif
selector = SelectKBest(score_func=f_classif, k=2)
X_new = selector.fit_transform(X, y)
print(f"Original shape: {X.shape}")
print(f"Reduced shape: {X_new.shape}")
# To see which features were selected:
selected_indices = selector.get_support(indices=True)
print(f"Selected feature indices: {selected_indices}")
print(f"Selected feature names: {[iris.feature_names[i] for i in selected_indices]}")
์ด ์์๋ ๋ถ๋ฅ๋ฅผ ์ํ ํต๊ณ์ ์ ์์ฑ์ ๊ธฐ๋ฐ์ผ๋ก 'k'๊ฐ์ ์ต์ ํน์ง์ ์ ํํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ค๋๋ค. f_classif์ F-๊ฐ์ ๊ธฐ๋ณธ์ ์ผ๋ก ๊ทธ๋ฃน(ํด๋์ค) ๊ฐ์ ๋ถ์ฐ์ ๊ทธ๋ฃน ๋ด ๋ถ์ฐ์ ์๋์ ์ผ๋ก ์ธก์ ํฉ๋๋ค. F-๊ฐ์ด ๋์์๋ก ํน์ง๊ณผ ํ๊ฒ ๊ฐ์ ๊ด๊ณ๊ฐ ๊ฐํ๋ค๋ ๊ฒ์ ๋ํ๋
๋๋ค.
๊ธ๋ก๋ฒ ๊ณ ๋ ค ์ฌํญ: ๋ค๋ฅธ ์ง์ญ์ ๋ฐ์ดํฐ์ (์: ๋ค์ํ ๊ธฐํ์ ์ผ์ ๋ฐ์ดํฐ, ๋ค๋ฅธ ๊ฒฝ์ ์์คํ ์ ๊ธ์ต ๋ฐ์ดํฐ)์ผ๋ก ์์ ํ ๋, ํน์ง์ ํต๊ณ์ ์์ฑ์ ํฌ๊ฒ ๋ฌ๋ผ์ง ์ ์์ต๋๋ค. ์ด๋ฌํ ํต๊ณ ํ ์คํธ์ ๊ฐ์ (์: ANOVA์ ์ ๊ท์ฑ)์ ์ดํดํ๋ ๊ฒ์ด ์ค์ํ๋ฉฐ, ์ํธ ์ ๋ณด์ ๊ฐ์ ๋น๋ชจ์์ ํ ์คํธ๋ ๋ค์ํ ์๋๋ฆฌ์ค์์ ๋ ๊ฐ๋ ฅํ ์ ์์ต๋๋ค.
2. ๋ํผ ๋ฐฉ๋ฒ
๋ํผ ๋ฐฉ๋ฒ์ ํน์ ๋จธ์ ๋ฌ๋ ๋ชจ๋ธ์ ์ฌ์ฉํ์ฌ ํน์ง ํ์ ์งํฉ์ ํ์ง์ ํ๊ฐํฉ๋๋ค. ์ด๋ค์ ๋ชจ๋ธ ํ๋ จ ํ๋ก์ธ์ค๋ฅผ ํ์ ์ ๋ต ๋ด์ '๊ฐ์ธ์' ์ต์ ์ ํน์ง ์งํฉ์ ์ฐพ์ต๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ํํฐ ๋ฐฉ๋ฒ๋ณด๋ค ์ ํํ์ง๋ง, ๋ชจ๋ธ ํ๋ จ์ ๋ฐ๋ณตํ๊ธฐ ๋๋ฌธ์ ๊ณ์ฐ ๋น์ฉ์ด ํจ์ฌ ๋ ๋ง์ด ๋ญ๋๋ค.
a) ์ฌ๊ท์ ํน์ง ์ ๊ฑฐ (RFE)
RFE๋ ํน์ง์ ์ฌ๊ท์ ์ผ๋ก ์ ๊ฑฐํ๋ ๋ฐฉ์์ผ๋ก ์๋ํฉ๋๋ค. ์ ์ฒด ํน์ง ์งํฉ์ผ๋ก ๋ชจ๋ธ์ ํ๋ จํ ๋ค์, ๋ชจ๋ธ์ ๊ณ์ ๋๋ ํน์ง ์ค์๋์ ๋ฐ๋ผ ๊ฐ์ฅ ์ค์๋๊ฐ ๋ฎ์ ํน์ง์ ์ ๊ฑฐํฉ๋๋ค. ์ด ๊ณผ์ ์ ์ํ๋ ์์ ํน์ง์ ๋๋ฌํ ๋๊น์ง ๋ฐ๋ณต๋ฉ๋๋ค.
from sklearn.datasets import make_classification
from sklearn.feature_selection import RFE
from sklearn.linear_model import LogisticRegression
# Generate synthetic data
X, y = make_classification(n_samples=100, n_features=20, n_informative=10, n_redundant=5, random_state=42)
# Use a Logistic Regression model (can be any model that supports coef_ or feature_importances_)
estimator = LogisticRegression(solver='liblinear')
# Initialize RFE to select top 5 features
selector = RFE(estimator, n_features_to_select=5, step=1)
selector = selector.fit(X, y)
X_new = selector.transform(X)
print(f"Original shape: {X.shape}")
print(f"Reduced shape: {X_new.shape}")
# To see which features were selected:
selected_indices = selector.get_support(indices=True)
print(f"Selected feature indices: {selected_indices}")
RFE๋ ์ ํ๋ ๋ชจ๋ธ์ด ํ๊ฐํ๋ ํน์ง๋ค ๊ฐ์ ์ํธ์์ฉ์ ๊ณ ๋ คํ๊ธฐ ๋๋ฌธ์ ๊ฐ๋ ฅํฉ๋๋ค. `step` ๋งค๊ฐ๋ณ์๋ ๊ฐ ๋ฐ๋ณต์์ ์ ๊ฑฐ๋๋ ํน์ง์ ์๋ฅผ ์ ์ดํฉ๋๋ค.
b) ์์ฐจ์ ํน์ง ์ ํ (SFS)
Scikit-learn ํต์ฌ feature_selection์ ์ง์ ์ ์ธ ํด๋์ค๋ ์๋์ง๋ง, ์์ฐจ์ ํน์ง ์ ํ์ Scikit-learn ์ถ์ ๊ธฐ(estimator)๋ฅผ ์ฌ์ฉํ์ฌ ์์ฃผ ๊ตฌํ๋๋ ๊ฐ๋
์ ์ ๊ทผ ๋ฐฉ์์
๋๋ค. ์ด๋ ์๋ฐฉํฅ ์ ํ(๋น ์งํฉ์์ ์์ํ์ฌ ํน์ง์ ํ๋์ฉ ์ถ๊ฐ) ๋๋ ํ๋ฐฉ ์ ๊ฑฐ(๋ชจ๋ ํน์ง์ผ๋ก ์์ํ์ฌ ํ๋์ฉ ์ ๊ฑฐ)๋ฅผ ํฌํจํฉ๋๋ค. sklearn.feature_selection์ Scikit-learn SequentialFeatureSelector๊ฐ ์ด๋ฅผ ๊ตฌํํฉ๋๋ค.
from sklearn.feature_selection import SequentialFeatureSelector
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import make_classification
X, y = make_classification(n_samples=100, n_features=20, n_informative=10, n_redundant=5, random_state=42)
estimator = LogisticRegression(solver='liblinear')
# Forward selection: add features until desired number is reached
sfs_forward = SequentialFeatureSelector(
estimator, n_features_to_select=10, direction='forward', cv=5)
sfs_forward.fit(X, y)
X_new_forward = sfs_forward.transform(X)
print(f"Forward Selection - Reduced shape: {X_new_forward.shape}")
# Backward selection: start with all features and remove
sfs_backward = SequentialFeatureSelector(
estimator, n_features_to_select=10, direction='backward', cv=5)
sfs_backward.fit(X, y)
X_new_backward = sfs_backward.transform(X)
print(f"Backward Selection - Reduced shape: {X_new_backward.shape}")
cv ๋งค๊ฐ๋ณ์๋ ๊ต์ฐจ ์ ํจ์ฑ ๊ฒ์ฌ(cross-validation)๋ฅผ ์๋ฏธํ๋ฉฐ, ์ด๋ ํน์ง ์ ํ์ ๋ ๊ฐ๋ ฅํ๊ฒ ๋ง๋ค๊ณ ํ๋ จ ๋ฐ์ดํฐ์ ๋ํ ๊ณผ์ ํฉ ์ํ์ ์ค์ด๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค. ๋ฐ์ดํฐ ํ์ง๊ณผ ๋ถํฌ๊ฐ ์์ฒญ๋๊ฒ ๋ค์ํ ์ ์์ผ๋ฏ๋ก ์ด๋ฌํ ๋ฐฉ๋ฒ์ ์ ์ธ๊ณ์ ์ผ๋ก ์ ์ฉํ ๋ ์ค์ํ ๊ณ ๋ ค ์ฌํญ์
๋๋ค.
3. ์๋ฒ ๋๋ ๋ฐฉ๋ฒ
์๋ฒ ๋๋ ๋ฐฉ๋ฒ์ ๋ชจ๋ธ ํ๋ จ ๊ณผ์ ์ ์ผ๋ถ๋ก ํน์ง ์ ํ์ ์ํํฉ๋๋ค. ์ด๋ค์ ํน์ง ์ํธ์์ฉ์ ์ฌ์ ํ ๊ณ ๋ คํ๋ฉด์ ๋ํผ ๋ฐฉ๋ฒ๋ณด๋ค ๊ณ์ฐ ๋น์ฉ์ด ์ ๊ฒ ๋ ๋ค๋ ์ฅ์ ์ด ์์ต๋๋ค. ๋ง์ ์ ๊ทํ๋ ๋ชจ๋ธ์ด ์ด ๋ฒ์ฃผ์ ์ํฉ๋๋ค.
a) L1 ์ ๊ทํ (๋ผ์)
์ ํ ๋ชจ๋ธ์ Lasso(Least Absolute Shrinkage and Selection Operator)์ ๊ฐ์ ๋ชจ๋ธ์ L1 ์ ๊ทํ๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์ด ๊ธฐ์ ์ ๊ณ์์ ์ ๋๊ฐ์ ํ๋ํฐ๋ฅผ ์ถ๊ฐํ์ฌ ์ผ๋ถ ๊ณ์๋ฅผ ์ ํํ 0์ผ๋ก ๋ง๋ค ์ ์์ต๋๋ค. ๊ณ์๊ฐ 0์ธ ํน์ง์ ํจ๊ณผ์ ์ผ๋ก ์ ๊ฑฐ๋ฉ๋๋ค.
from sklearn.linear_model import Lasso
from sklearn.datasets import make_regression
# Generate synthetic data
X, y = make_regression(n_samples=100, n_features=20, n_informative=10, random_state=42, noise=10)
# Lasso with alpha (regularization strength)
# A higher alpha leads to more regularization and potentially more zero coefficients
lasso = Lasso(alpha=0.1, random_state=42)
lasso.fit(X, y)
# Get the number of non-zero coefficients (selected features)
non_zero_features = np.sum(lasso.coef_ != 0)
print(f"Number of features selected by Lasso: {non_zero_features}")
# To get the actual selected features:
selected_features_mask = lasso.coef_ != 0
X_new = X[:, selected_features_mask]
print(f"Reduced shape: {X_new.shape}")
LassoCV๋ ๊ต์ฐจ ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ํตํด ์ต์ ์ ์ํ ๊ฐ์ ์๋์ผ๋ก ์ฐพ๋ ๋ฐ ์ฌ์ฉ๋ ์ ์์ต๋๋ค.
b) ํธ๋ฆฌ ๊ธฐ๋ฐ ํน์ง ์ค์๋
RandomForestClassifier, GradientBoostingClassifier, ExtraTreesClassifier์ ๊ฐ์ ์์๋ธ ๋ฐฉ๋ฒ์ ๋ณธ์ง์ ์ผ๋ก ํน์ง ์ค์๋๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ด๋ค์ ๊ฐ ํน์ง์ด ์์๋ธ ๋ด์ ํธ๋ฆฌ ์ ์ฒด์์ ๋ถ์๋ ๋๋ ์ค๋ฅ๋ฅผ ์ค์ด๋ ๋ฐ ์ผ๋ง๋ ๊ธฐ์ฌํ๋์ง์ ๋ฐ๋ผ ๊ณ์ฐ๋ฉ๋๋ค. ์ค์๋๊ฐ ๋ฎ์ ํน์ง์ ์ ๊ฑฐ๋ ์ ์์ต๋๋ค.
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_breast_cancer
cancer = load_breast_cancer()
X, y = cancer.data, cancer.target
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X, y)
# Get feature importances
importances = model.feature_importances_
# Sort features by importance
indices = np.argsort(importances)[::-1]
print("Feature ranking:")
for f in range(X.shape[1]):
print(f"{f + 1}. feature {indices[f]} ({cancer.feature_names[indices[f]]}) - {importances[indices[f]]:.4f}")
# Select top N features (e.g., top 10)
N = 10
selected_features_mask = np.zeros(X.shape[1], dtype=bool)
selected_features_mask[indices[:N]] = True
X_new = X[:, selected_features_mask]
print(f"Reduced shape after selecting top {N} features: {X_new.shape}")
ํธ๋ฆฌ ๊ธฐ๋ฐ ๋ฐฉ๋ฒ์ ๋น์ ํ ๊ด๊ณ ๋ฐ ํน์ง ์ํธ์์ฉ์ ํฌ์ฐฉํ ์ ์๊ธฐ ๋๋ฌธ์ ๊ฐ๋ ฅํฉ๋๋ค. ์ด๋ค์ ์๋ฃ ์ง๋จ(์์์ ๊ฐ์ด)๋ถํฐ ๋ค์ํ ์์ฅ์์์ ๊ธ์ต ์ฌ๊ธฐ ํ์ง์ ์ด๋ฅด๊ธฐ๊น์ง ๋ค์ํ ๋ถ์ผ์ ๋๋ฆฌ ์ ์ฉ ๊ฐ๋ฅํฉ๋๋ค.
์ฐจ์ ์ถ์๋ฅผ ์ํ ํน์ง ์ถ์ถ
ํน์ง ์ ํ์ด ์๋ณธ ํน์ง์ ์ ์งํ๋ ๋ฐ๋ฉด, ํน์ง ์ถ์ถ์ ์๋กญ๊ณ ์ถ์๋ ํน์ง ์งํฉ์ ์์ฑํฉ๋๋ค. ์ด๋ ์๋ณธ ํน์ง๋ค์ด ๋์ ์๊ด๊ด๊ณ๋ฅผ ๊ฐ์ง๊ฑฐ๋, ๋ฐ์ดํฐ์ ๋๋ถ๋ถ์ ๋ถ์ฐ์ ํฌ์ฐฉํ๋ ์ ์ฐจ์ ๊ณต๊ฐ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ํฌ์ํ๊ณ ์ ํ ๋ ํนํ ์ ์ฉํฉ๋๋ค.
1. ์ฃผ์ฑ๋ถ ๋ถ์ (PCA)
PCA๋ ๋ฐ์ดํฐ์์ ์ต๋ ๋ถ์ฐ์ ํฌ์ฐฉํ๋ ์ผ๋ จ์ ์ง๊ต ์ถ(์ฃผ์ฑ๋ถ)์ ์ฐพ๋ ๊ฒ์ ๋ชฉํ๋ก ํ๋ ์ ํ ๋ณํ ๊ธฐ์ ์ ๋๋ค. ์ฒซ ๋ฒ์งธ ์ฃผ์ฑ๋ถ์ ๊ฐ์ฅ ๋ง์ ๋ถ์ฐ์ ํฌ์ฐฉํ๊ณ , ๋ ๋ฒ์งธ ์ฃผ์ฑ๋ถ์ ๊ทธ ๋ค์์ผ๋ก ๋ง์ ๋ถ์ฐ(์ฒซ ๋ฒ์งธ์ ์ง๊ต)์ ํฌ์ฐฉํ๋ ์์ ๋๋ค. ์ฒ์ 'k'๊ฐ์ ์ฃผ์ฑ๋ถ๋ง ์ ์งํจ์ผ๋ก์จ ์ฐจ์ ์ถ์๋ฅผ ๋ฌ์ฑํฉ๋๋ค.
์ค์ ์ฌํญ: PCA๋ ํน์ง์ ์ค์ผ์ผ์ ๋ฏผ๊ฐํฉ๋๋ค. PCA๋ฅผ ์ ์ฉํ๊ธฐ ์ ์ ๋ฐ์ดํฐ๋ฅผ ์ค์ผ์ผ๋งํ๋ ๊ฒ(์: StandardScaler ์ฌ์ฉ)์ด ์ค์ํฉ๋๋ค.
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from sklearn.datasets import load_wine
wine = load_wine()
X, y = wine.data, wine.target
# Scale the data
X_scaled = StandardScaler().fit_transform(X)
# Initialize PCA to reduce to 2 components
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X_scaled)
print(f"Original shape: {X.shape}")
print(f"Reduced shape after PCA: {X_pca.shape}")
# The explained variance ratio shows how much variance each component captures
print(f"Explained variance ratio: {pca.explained_variance_ratio_}")
print(f"Total explained variance: {np.sum(pca.explained_variance_ratio_):.4f}")
PCA๋ ๊ณ ์ฐจ์ ๋ฐ์ดํฐ๋ฅผ 2D ๋๋ 3D๋ก ์ค์ฌ ์๊ฐํํ๋ ๋ฐ ํ์ํฉ๋๋ค. ์ด๋ ํ์์ ๋ฐ์ดํฐ ๋ถ์์ ๊ธฐ๋ณธ ๊ธฐ์ ์ด๋ฉฐ ํ์ ๋ชจ๋ธ๋ง ๋จ๊ณ๋ฅผ ํฌ๊ฒ ๊ฐ์ํํ ์ ์์ต๋๋ค. ๊ทธ ํจ๊ณผ๋ ์ด๋ฏธ์ง ์ฒ๋ฆฌ ๋ฐ ์ ์ ํ ๊ฐ์ ๋ถ์ผ์์ ๊ด์ฐฐ๋ฉ๋๋ค.
2. ์ ํ ํ๋ณ ๋ถ์ (LDA)
๋น์ง๋ ํ์ต์ด๋ฉฐ ๋ถ์ฐ์ ์ต๋ํํ๋ ๊ฒ์ ๋ชฉํ๋ก ํ๋ PCA์ ๋ฌ๋ฆฌ, LDA๋ ํด๋์ค ๊ฐ์ ๋ถ๋ฆฌ ๊ฐ๋ฅ์ฑ์ ์ต๋ํํ๋ ์ ์ฐจ์ ํํ์ ์ฐพ๋ ๊ฒ์ ๋ชฉํ๋ก ํ๋ ์ง๋ ํ์ต ๊ธฐ์ ์ ๋๋ค. ์ด๋ ์ฃผ๋ก ๋ถ๋ฅ ์์ ์ ์ฌ์ฉ๋ฉ๋๋ค.
์ค์ ์ฌํญ: LDA ๋ํ ํน์ง์ ์ค์ผ์ผ๋งํด์ผ ํฉ๋๋ค. ๋ํ LDA์ ๊ตฌ์ฑ ์์ ์๋ ์ต๋ n_classes - 1๋ก ์ ํ๋ฉ๋๋ค.
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import load_iris
iris = load_iris()
X, y = iris.data, iris.target
# Scale the data
X_scaled = StandardScaler().fit_transform(X)
# Initialize LDA. Number of components cannot exceed n_classes - 1 (which is 2 for Iris)
lda = LinearDiscriminantAnalysis(n_components=2)
X_lda = lda.fit_transform(X_scaled, y)
print(f"Original shape: {X.shape}")
print(f"Reduced shape after LDA: {X_lda.shape}")
# LDA also has explained_variance_ratio_ but it's class separability
print(f"Explained variance ratio (class separability): {lda.explained_variance_ratio_}")
LDA๋ ๋ฐ์ดํฐ์ ๋ค๋ฅธ ๋ฒ์ฃผ๋ฅผ ์ ๊ตฌ๋ณํ ์ ์๋ ๋ถ๋ฅ๊ธฐ๋ฅผ ๊ตฌ์ถํ๋ ๊ฒ์ด ๋ชฉํ์ผ ๋ ํนํ ์ ์ฉํ๋ฉฐ, ์ด๋ ๊ณ ๊ฐ ์ธ๋ถํ ๋๋ ์ง๋ณ ๋ถ๋ฅ์ ๊ฐ์ ๋ง์ ๊ธ๋ก๋ฒ ์ ํ๋ฆฌ์ผ์ด์ ์์ ํํ ๋ฐ์ํ๋ ๊ณผ์ ์ ๋๋ค.
3. t-๋ถํฌ ํ๋ฅ ์ ์ด์ ์๋ฒ ๋ฉ (t-SNE)
t-SNE๋ ์ฃผ๋ก ๊ณ ์ฐจ์ ๋ฐ์ดํฐ์ ์ ์๊ฐํํ๋ ๋ฐ ์ฌ์ฉ๋๋ ๋น์ ํ ์ฐจ์ ์ถ์ ๊ธฐ์ ์ ๋๋ค. ์ด๋ ๊ณ ์ฐจ์ ๋ฐ์ดํฐ ํฌ์ธํธ๋ฅผ ์ ์ฐจ์ ๊ณต๊ฐ(์ผ๋ฐ์ ์ผ๋ก 2D ๋๋ 3D)์ผ๋ก ๋งคํํ์ฌ, ์ ์ฌํ ์ ๋ค์ด ์ ์ฐจ์ ๊ณต๊ฐ์์ ์ ์ฌํ ๊ฑฐ๋ฆฌ๋ก ๋ชจ๋ธ๋ง๋๋๋ก ํฉ๋๋ค. ๋ฐ์ดํฐ ๋ด์ ์ง์ญ ๊ตฌ์กฐ์ ํด๋ฌ์คํฐ๋ฅผ ๋๋ฌ๋ด๋ ๋ฐ ํ์ํฉ๋๋ค.
์ค์ ์ฌํญ: t-SNE๋ ๊ณ์ฐ ๋น์ฉ์ด ๋ง์ด ๋ค๊ณ ์ผ๋ฐ์ ์ผ๋ก ๋ชจ๋ธ ํ๋ จ์ ์ํ ์ ์ฒ๋ฆฌ ๋จ๊ณ๋ณด๋ค๋ ์๊ฐํ๋ฅผ ์ํด ์ฌ์ฉ๋ฉ๋๋ค. ๊ฒฐ๊ณผ๋ ๋ํ ๋ค๋ฅธ ๋ฌด์์ ์ด๊ธฐํ ๋ฐ ๋งค๊ฐ๋ณ์ ์ค์ ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง ์ ์์ต๋๋ค.
from sklearn.manifold import TSNE
from sklearn.datasets import load_digits
import matplotlib.pyplot as plt
digits = load_digits()
X, y = digits.data, digits.target
# For demonstration, we'll use a subset of the data as t-SNE can be slow
subset_indices = np.random.choice(len(X), 1000, replace=False)
X_subset = X[subset_indices]
y_subset = y[subset_indices]
# Initialize t-SNE with 2 components
# perplexity is related to the number of nearest neighbors (e.g., 30 is common)
# n_iter is the number of iterations for optimization
tsne = TSNE(n_components=2, perplexity=30, n_iter=300, random_state=42)
X_tsne = tsne.fit_transform(X_subset)
print(f"Original subset shape: {X_subset.shape}")
print(f"Reduced shape after t-SNE: {X_tsne.shape}")
# Plotting the results (optional, for visualization)
plt.figure(figsize=(10, 8))
scatter = plt.scatter(X_tsne[:, 0], X_tsne[:, 1], c=y_subset, cmap='viridis', alpha=0.7)
plt.title('t-SNE visualization of Digits dataset')
plt.xlabel('t-SNE component 1')
plt.ylabel('t-SNE component 2')
plt.legend(*scatter.legend_elements(), title='Classes')
plt.show()
t-SNE๋ ์ ์ ์ฒดํ ๋๋ ์์ ๋คํธ์ํฌ ๋ถ์๊ณผ ๊ฐ์ ๋ถ์ผ์์ ์ ํ๋ ๋ณต์กํ๊ณ ๊ณ ์ฐจ์ ๋ฐ์ดํฐ์ ๋ด์ฌ๋ ๊ตฌ์กฐ๋ฅผ ์ดํดํ๋ ๋ฐ ๋งค์ฐ ์ ์ฉํ๋ฉฐ, ๊ทธ๋ ์ง ์์ผ๋ฉด ์จ๊ฒจ์ ธ ์์ ์ ์๋ ํจํด์ ๋ํ ์๊ฐ์ ํต์ฐฐ๋ ฅ์ ์ ๊ณตํฉ๋๋ค.
๊ธ๋ก๋ฒ ๋ฐ์ดํฐ์ ์ ์ ํฉํ ๊ธฐ๋ฒ ์ ํํ๊ธฐ
์ ์ ํ ํน์ง ์ ํ ๋๋ ์ถ์ถ ๋ฐฉ๋ฒ์ ์ ํํ๋ ๊ฒ์ ๋ชจ๋ ๊ฒฝ์ฐ์ ์ ์ฉ๋๋ ๋จ์ผ ๊ฒฐ์ ์ด ์๋๋๋ค. ํนํ ๊ธ๋ก๋ฒ ๋ฐ์ดํฐ์ ์ ๊ฒฝ์ฐ ์ฌ๋ฌ ์์ธ์ด ์ด๋ฌํ ์ ํ์ ์ํฅ์ ๋ฏธ์นฉ๋๋ค:
- ๋ฐ์ดํฐ์ ํน์ฑ: ๋ฐ์ดํฐ๊ฐ ์ซ์ํ, ๋ฒ์ฃผํ ๋๋ ํผํฉํ์
๋๊น? ์๋ ค์ง ๋ถํฌ๊ฐ ์์ต๋๊น? ์๋ฅผ ๋ค์ด,
chi2๋ ์์ด ์๋ ๋ฒ์ฃผํ ํน์ง์ ์ ํฉํ๊ณ ,f_classif๋ ์ซ์ํ ํน์ง๊ณผ ๋ฒ์ฃผํ ํ๊ฒ์ ์ ํฉํฉ๋๋ค. - ๋ชจ๋ธ ์ ํ: ์ ํ ๋ชจ๋ธ์ L1 ์ ๊ทํ์ ์ด์ ์ ์ป์ ์ ์์ผ๋ฉฐ, ํธ๋ฆฌ ๊ธฐ๋ฐ ๋ชจ๋ธ์ ์์ฐ์ค๋ฝ๊ฒ ์ค์๋๋ฅผ ์ ๊ณตํฉ๋๋ค.
- ๊ณ์ฐ ์์: ํํฐ ๋ฐฉ๋ฒ์ด ๊ฐ์ฅ ๋น ๋ฅด๊ณ , ๊ทธ ๋ค์์ผ๋ก ์๋ฒ ๋๋ ๋ฐฉ๋ฒ, ๊ทธ๋ฆฌ๊ณ ๋ํผ ๋ฐฉ๋ฒ๊ณผ t-SNE ์์ ๋๋ค.
- ํด์ ๊ฐ๋ฅ์ฑ ์๊ตฌ ์ฌํญ: ์์ธก์ด *์* ์ด๋ฃจ์ด์ก๋์ง ์ค๋ช ํ๋ ๊ฒ์ด ๊ฐ์ฅ ์ค์ํ๋ค๋ฉด, ์ถ์์ ์ธ ๊ตฌ์ฑ ์์๋ฅผ ์์ฑํ๋ ํน์ง ์ถ์ถ ๋ฐฉ๋ฒ(PCA ๋ฑ)๋ณด๋ค ์๋ณธ ํน์ง์ ์ ์งํ๋ ํน์ง ์ ํ ๋ฐฉ๋ฒ(RFE ๋๋ L1 ๋ฑ)์ด ์ข ์ข ์ ํธ๋ฉ๋๋ค.
- ์ ํ์ฑ ๋ ๋น์ ํ์ฑ: PCA์ ์ ํ ๋ชจ๋ธ์ ์ ํ ๊ด๊ณ๋ฅผ ๊ฐ์ ํ๋ ๋ฐ๋ฉด, t-SNE์ ํธ๋ฆฌ ๊ธฐ๋ฐ ๋ฐฉ๋ฒ์ ๋น์ ํ ํจํด์ ํฌ์ฐฉํ ์ ์์ต๋๋ค.
- ์ง๋ ํ์ต ๋ ๋น์ง๋ ํ์ต: LDA๋ ์ง๋ ํ์ต(ํ๊ฒ ๋ณ์ ์ฌ์ฉ)์ด๊ณ , PCA๋ ๋น์ง๋ ํ์ต์ ๋๋ค.
- ์ค์ผ์ผ ๋ฐ ๋จ์: PCA์ LDA์ ๊ฒฝ์ฐ ํน์ง ์ค์ผ์ผ๋ง์ด ํ์์ ์ ๋๋ค. ๋ค๋ฅธ ๊ธ๋ก๋ฒ ์ง์ญ์์ ์์ง๋ ๋ฐ์ดํฐ์ ์ค์ผ์ผ ์ฐจ์ด๋ฅผ ๊ณ ๋ คํ์ญ์์ค. ์๋ฅผ ๋ค์ด, ํตํ ๊ฐ์น ๋๋ ์ผ์ ํ๋ ๊ฐ์ ๊ตญ๊ฐ ๋๋ ์ผ์ ์ ํ์ ๋ฐ๋ผ ํฌ๊ฒ ๋ค๋ฅผ ์ ์์ต๋๋ค.
- ๋ฌธํ์ ๋ฐ ์ง์ญ์ ๋์์ค: ๋ค์ํ ๋ฌธํ์ ๋งฅ๋ฝ์์ ์ธ๊ฐ ํ๋, ์ธ๊ตฌ ํต๊ณ ๋๋ ๊ฐ์ ๊ณผ ๊ด๋ จ๋ ๋ฐ์ดํฐ์ ์ผ๋ก ์์ ํ ๋, ํน์ง์ ํด์์ ๋ณต์กํ ์ ์์ต๋๋ค. ํ ์ง์ญ์์ ๋งค์ฐ ์์ธก๋ ฅ์ด ๋์ ํน์ง์ ๋ค๋ฅธ ์ฌํ์ ๊ท๋ฒ, ๊ฒฝ์ ์ ์กฐ๊ฑด ๋๋ ๋ฐ์ดํฐ ์์ง ๋ฐฉ๋ฒ๋ก ์ผ๋ก ์ธํด ๋ค๋ฅธ ์ง์ญ์์๋ ๊ด๋ จ์ด ์๊ฑฐ๋ ์ฌ์ง์ด ์คํด์ ์์ง๊ฐ ์์ ์ ์์ต๋๋ค. ๋ค์ํ ์ธ๊ตฌ ์ง๋จ์ ๊ฑธ์ณ ํน์ง ์ค์๋๋ฅผ ํ๊ฐํ ๋ ํญ์ ๋๋ฉ์ธ ์ ๋ฌธ ์ง์์ ๊ณ ๋ คํ์ญ์์ค.
์ค์ฉ์ ์ธ ํต์ฐฐ:
- ๊ฐ๋จํ๊ฒ ์์: ๋น ๋ฅธ ํ๊ฐ ๋ฐ ๋ช ๋ฐฑํ ๋ ธ์ด์ฆ ์ ๊ฑฐ๋ฅผ ์ํด ํํฐ ๋ฐฉ๋ฒ(์: ๋ถ์ฐ ์๊ณ๊ฐ, ํต๊ณ ํ ์คํธ)๋ถํฐ ์์ํ์ญ์์ค.
- ๋ฐ๋ณต ๋ฐ ํ๊ฐ: ๋ค์ํ ๋ฐฉ๋ฒ์ ์คํํ๊ณ ์ ์ ํ ์งํ์ ๊ต์ฐจ ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ์ฌ์ฉํ์ฌ ๋ชจ๋ธ ์ฑ๋ฅ์ ๋ฏธ์น๋ ์ํฅ์ ํ๊ฐํ์ญ์์ค.
- ์๊ฐํ: PCA ๋๋ t-SNE์ ๊ฐ์ ๊ธฐ์ ์ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ์ ์ฐจ์์์ ์๊ฐํํ๋ฉด, ๊ธฐ๋ณธ ๊ตฌ์กฐ๋ฅผ ๋๋ฌ๋ด๊ณ ํน์ง ์ ํ ์ ๋ต์ ์ ๋ณด๋ฅผ ์ ๊ณตํ ์ ์์ต๋๋ค.
- ๋๋ฉ์ธ ์ ๋ฌธ ์ง์์ ํต์ฌ: ๋ณต์กํ ๊ธ๋ก๋ฒ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃฐ ๋ ํนํ ํน์ง์ ์๋ฏธ์ ๊ด๋ จ์ฑ์ ์ดํดํ๊ธฐ ์ํด ๋๋ฉ์ธ ์ ๋ฌธ๊ฐ์ ํ๋ ฅํ์ญ์์ค.
- ์์๋ธ ์ ๊ทผ๋ฒ ๊ณ ๋ ค: ์ฌ๋ฌ ํน์ง ์ ํ ๊ธฐ์ ์ ๊ฒฐํฉํ๋ฉด ๋จ์ผ ๋ฐฉ๋ฒ์ ์์กดํ๋ ๊ฒ๋ณด๋ค ๋ ๋์ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์์ต๋๋ค.
ํตํฉ ์ํฌํ๋ก๋ฅผ ์ํ Scikit-learn์ ํ์ดํ๋ผ์ธ
Scikit-learn์ Pipeline ๊ฐ์ฒด๋ ํน์ง ์ ํ/์ถ์ถ์ ํฌํจํ ์ ์ฒ๋ฆฌ ๋จ๊ณ๋ฅผ ๋ชจ๋ธ ํ๋ จ๊ณผ ํตํฉํ๋ ๋ฐ ๋งค์ฐ ์ ์ฉํฉ๋๋ค. ์ด๋ ํน์ง ์ ํ์ด ๊ต์ฐจ ์ ํจ์ฑ ๊ฒ์ฌ์ ๊ฐ ํด๋ ๋ด์์ ์ผ๊ด๋๊ฒ ์ํ๋๋๋ก ๋ณด์ฅํ์ฌ, ๋ฐ์ดํฐ ๋์๋ฅผ ๋ฐฉ์งํ๊ณ ๋ ์ ๋ขฐํ ์ ์๋ ๊ฒฐ๊ณผ๋ฅผ ์์ฑํฉ๋๋ค. ์ด๋ ๋ค์ํ ๊ธ๋ก๋ฒ ์์ฅ์ ๋ฐฐํฌ๋ ๋ชจ๋ธ์ ๊ตฌ์ถํ ๋ ํนํ ์ค์ํฉ๋๋ค.
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.feature_selection import SelectKBest, f_classif
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.datasets import load_breast_cancer
bc = load_breast_cancer()
X, y = bc.data, bc.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# Create a pipeline that first scales, then selects features, then trains a classifier
pipe = Pipeline([
('scaler', StandardScaler()),
('selector', SelectKBest(score_func=f_classif, k=10)),
('classifier', LogisticRegression(solver='liblinear'))
])
# Train the pipeline
pipe.fit(X_train, y_train)
# Evaluate the pipeline using cross-validation
cv_scores = cross_val_score(pipe, X_train, y_train, cv=5)
print(f"Cross-validation scores: {cv_scores}")
print(f"Average CV score: {np.mean(cv_scores):.4f}")
# Make predictions on the test set
accuracy = pipe.score(X_test, y_test)
print(f"Test set accuracy: {accuracy:.4f}")
ํ์ดํ๋ผ์ธ์ ์ฌ์ฉํ๋ฉด ์ค์ผ์ผ๋ง๋ถํฐ ํน์ง ์ ํ, ๋ถ๋ฅ์ ์ด๋ฅด๋ ์ ์ฒด ํ๋ก์ธ์ค๊ฐ ๋จ์ผ ์ํฐํฐ๋ก ์ฒ๋ฆฌ๋ฉ๋๋ค. ์ด๋ ๊ฐ๋ ฅํ ๋ชจ๋ธ ๊ฐ๋ฐ์ ์ํ ๋ชจ๋ฒ ์ฌ๋ก์ด๋ฉฐ, ํนํ ๋ค์ํ ๋ฐ์ดํฐ ๋ถํฌ์์ ์ผ๊ด๋ ์ฑ๋ฅ์ด ํต์ฌ์ธ ๊ธ๋ก๋ฒ ๋ฐฐํฌ๋ฅผ ์ํ ๋ชจ๋ธ์ ์ค์ํฉ๋๋ค.
๊ฒฐ๋ก
ํน์ง ์ ํ ๋ฐ ์ถ์ถ์ ํตํ ์ฐจ์ ์ถ์๋ ํจ์จ์ ์ด๊ณ ๊ฒฌ๊ณ ํ๋ฉฐ ํด์ ๊ฐ๋ฅํ ๋จธ์ ๋ฌ๋ ๋ชจ๋ธ์ ๊ตฌ์ถํ๋ ๋ฐ ํ์์ ์ธ ๋จ๊ณ์ ๋๋ค. Scikit-learn์ ์ด๋ฌํ ๊ณผ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํ ํฌ๊ด์ ์ธ ๋๊ตฌ ํคํธ๋ฅผ ์ ๊ณตํ์ฌ ์ ์ธ๊ณ ๋ฐ์ดํฐ ๊ณผํ์๋ค์๊ฒ ํ์ ์ค์ด์ค๋๋ค. ํํฐ, ๋ํผ, ์๋ฒ ๋๋ ๋ฐฉ๋ฒ, ๊ทธ๋ฆฌ๊ณ PCA ๋ฐ LDA์ ๊ฐ์ ํน์ง ์ถ์ถ ๊ธฐ์ ๊ณผ ๊ฐ์ ๋ค์ํ ๋ฐฉ๋ฒ๋ก ์ ์ดํดํจ์ผ๋ก์จ ํน์ ๋ฐ์ดํฐ์ ๊ณผ ๋ชฉํ์ ๋ง๋ ์ ๋ณด์ ์ ๊ฐํ ๊ฒฐ์ ์ ๋ด๋ฆด ์ ์์ต๋๋ค.
๊ธ๋ก๋ฒ ๋
์ ์ฌ๋ฌ๋ถ์๊ฒ๋ ๊ณ ๋ ค ์ฌํญ์ด ์๊ณ ๋ฆฌ์ฆ ์ ํ์ ๋์ด์ญ๋๋ค. ๋ฐ์ดํฐ ์ถ์ฒ, ๋ค๋ฅธ ์ง์ญ์์ ํน์ง ์์ง์ผ๋ก ์ธํด ๋ฐ์ํ ์ ์๋ ์ ์ฌ์ ํธํฅ, ๊ทธ๋ฆฌ๊ณ ์ง์ญ ์ดํด๊ด๊ณ์์ ํน์ ํด์ ๊ฐ๋ฅ์ฑ ์๊ตฌ ์ฌํญ์ ์ดํดํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. Scikit-learn์ Pipeline๊ณผ ๊ฐ์ ๋๊ตฌ๋ฅผ ํ์ฉํ๋ฉด ๊ตฌ์กฐํ๋๊ณ ์ฌํ ๊ฐ๋ฅํ ์ํฌํ๋ก๊ฐ ๋ณด์ฅ๋๋ฉฐ, ์ด๋ ๋ค์ํ ๊ตญ์ ์ ๋งฅ๋ฝ์์ ์ ๋ขฐํ ์ ์๋ AI ์๋ฃจ์
์ ๋ฐฐํฌํ๋ ๋ฐ ํ์์ ์
๋๋ค.
ํ๋ ๋ฐ์ดํฐ ๊ณผํ์ ๋ณต์ก์ฑ์ ํ์ํจ์ ๋ฐ๋ผ, Scikit-learn์ ํน์ง ์ ํ ๊ธฐ๋ฅ์ ๋ง์คํฐํ๋ ๊ฒ์ ์์ฌํ ์ฌ์ง ์์ด ์ค์ํ ์์ฐ์ด ๋ ๊ฒ์ด๋ฉฐ, ๋ฐ์ดํฐ์ ์ถ์ฒ์ ๊ด๊ณ์์ด ๋ฐ์ดํฐ์ ๋ชจ๋ ์ ์ฌ๋ ฅ์ ๋ฐํํ ์ ์๊ฒ ํด์ค ๊ฒ์ ๋๋ค.